package fr.umlv.cmis.treeview;

import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.dnd.Autoscroll;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Collections;

import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import org.apache.chemistry.opencmis.client.api.CmisObject;
import org.apache.chemistry.opencmis.client.api.Document;
import org.apache.chemistry.opencmis.client.api.Folder;
import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;




// TODO: Auto-generated Javadoc
/**
 * The Class CmisObjectTreeView.
 */
public class CmisObjectTreeView extends JTree implements Autoscroll {

	/** The Constant serialVersionUID. */
	private static final long serialVersionUID = 1L;
	
	/** The Constant defaultScrollInsets. */
	public static final Insets defaultScrollInsets = new Insets(8, 8, 8, 8);
	
	/** The scroll insets. */
	protected Insets scrollInsets = defaultScrollInsets;
	
	/** The model. */
	private CmiSObjectTreeModel model;

	/**
	 * Instantiates a new cmis object tree view.
	 *
	 * @param path the path
	 * @throws FileNotFoundException the file not found exception
	 * @throws SecurityException the security exception
	 */
	public CmisObjectTreeView(String path) throws FileNotFoundException, SecurityException {
		super((TreeModel)null);      // Create the JTree itself

		CmisObjectTreeViewCellRenderer renderer = new CmisObjectTreeViewCellRenderer();
		this.model = new CmiSObjectTreeModel();

      //  TreeCellEditor cellEditor = new ShellTreeViewCellEditor(this,renderer);
       
        
        setModel(model);
        setRootVisible(true);
        setShowsRootHandles(true);
        putClientProperty("JTree.lineStyle", "Angled");
        setEditable(true);
        setCellRenderer(renderer);
        setCellEditor(cellEditor);
        
        TreeSelectionModel selectionModel = getSelectionModel();
        selectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        
        //setDragEnabled(true);
        //setTransferHandler(new ShellTreeViewTransferHandler());
		// Listen for Tree Selection Events
	}

	

	// Autoscrolling support
	/**
	 * Sets the scroll insets.
	 *
	 * @param insets the new scroll insets
	 */
	public void setScrollInsets(Insets insets) {
		this.scrollInsets = insets;
	}

	/**
	 * Gets the scroll insets.
	 *
	 * @return the scroll insets
	 */
	public Insets getScrollInsets() {
		return scrollInsets;
	}

	// Implementation of Autoscroll interface
	/* (non-Javadoc)
	 * @see java.awt.dnd.Autoscroll#getAutoscrollInsets()
	 */
	public Insets getAutoscrollInsets() {
		Rectangle r = getVisibleRect();
		Dimension size = getSize();
		Insets i = new Insets(r.y + scrollInsets.top, r.x + scrollInsets.left, 
				size.height - r.y - r.height + scrollInsets.bottom, 
				size.width - r.x - r.width + scrollInsets.right);
		return i;
	}

	/* (non-Javadoc)
	 * @see java.awt.dnd.Autoscroll#autoscroll(java.awt.Point)
	 */
	public void autoscroll(Point location) {
		JScrollPane scroller = 
			(JScrollPane)SwingUtilities.getAncestorOfClass(JScrollPane.class, this);
		if (scroller != null) {
			JScrollBar hBar = scroller.getHorizontalScrollBar();
			JScrollBar vBar = scroller.getVerticalScrollBar();
			Rectangle r = getVisibleRect();
			if (location.x <= r.x + scrollInsets.left) {
				// Need to scroll left
				hBar.setValue(hBar.getValue() - hBar.getUnitIncrement(-1));
			}
			if (location.y <= r.y + scrollInsets.top) {
				// Need to scroll up
				vBar.setValue(vBar.getValue() - vBar.getUnitIncrement(-1));
			}
			if (location.x >= r.x + r.width - scrollInsets.right) {
				// Need to scroll right
				hBar.setValue(hBar.getValue() + hBar.getUnitIncrement(1));
			}
			if (location.y >= r.y + r.height - scrollInsets.bottom) {
				// Need to scroll down
				vBar.setValue(vBar.getValue() + vBar.getUnitIncrement(1));
			}
		}
	}

	/**
	 * Sets the selection.
	 *
	 * @param file the new selection
	 */
	public void setSelection(CmisObject file) {
        if (file == null) {
            throw new IllegalArgumentException("Cannot set a null value");
        }
               
        java.util.List<CmisObject> l = new ArrayList<CmisObject>();
        
        java.util.List<Folder> folders = new ArrayList<Folder>();
        
        // create the list start from dir position to root
        l.add(file);
        
        if(BaseTypeId.CMIS_FOLDER.equals(file.getBaseTypeId())){
        	folders = ((Folder)file).getParents();
        }else if(BaseTypeId.CMIS_DOCUMENT.equals(file.getBaseTypeId())){     	
        	folders = ((Document)file).getParents();
        }
        
        for(Folder f : folders){
    		l.add(f);
        }
        
        // reverse the list, so it start with root dir
        Collections.reverse(l);
        
        boolean found = false;
        CmisObjectTreeNode node = (CmisObjectTreeNode)getModel().getRoot();
        CmisObjectTreeNode childNode;
        
        for (int i=1;i<l.size();i++) {
            found = false;
            
            // seach in the current node children
            for (int j=0; j<node.getChildCount(); j++) {
                childNode = (CmisObjectTreeNode)node.getChildAt(j);
                CmisObject f = childNode.getCmisObject();
                
                if (f.getId().compareTo(l.get(i).getId()) == 0) {
                    node = childNode;
                    if (i < l.size()-1) {
                        expandPath(new TreePath(node.getPath()));
                    }
                    found = true;
                    break;
                }
            }
            
            if (found == false) { break; }
        }
        
        if (found == true) {
            TreePath treePath = new TreePath(node.getPath());
            setSelectionPath(treePath);
            scrollPathToVisible(treePath);
        }
    }
	
    /**
     * Gets the last selection.
     *
     * @return the last selection
     */
    public CmisObject getLastSelection() {
        CmisObject file = null;
        CmisObjectTreeNode node = (CmisObjectTreeNode)getLastSelectedPathComponent();
        if (node != null) {
            file = node.getCmisObject();
        }
        return file;
    }
    
    /**
     * Gets the cmis object tree model.
     *
     * @return the cmis object tree model
     */
    public CmiSObjectTreeModel getCmisObjectTreeModel(){
    	return this.model;
    }
    
    public void refresh() {	
    	model.refresh();
	}

}